import { reactive, toRefs } from "vue"
import { defineStore } from "pinia"
import * as cache from "@/utils/cache";
import { GetToken, SetToken, RemoveToken } from "@/utils/cookie";
import { GetUserPermission } from "@/api/system/user";
import { Login, RefreshToken } from "@/api/oAuth";
import router from "@/router";
import { useAppStore } from "@/store/app";
import { useViewTagStore } from "@/store/viewTag";

export interface UserStates {
  /** token */
  token: string | undefined;
  /** refreshToken */
  refreshToken: string | undefined;
  /** isRefreshToken */
  isRefreshToken: boolean;
  /** userName */
  userName: string;
  /** avatar */
  avatar: string;
  /** menus */
  menus: any[];
}

export const useUserStore = defineStore("userStore", () => {
  const appStore = useAppStore();
  const viewTagStore = useViewTagStore();

  const state = reactive<UserStates>(
    {
      token: GetToken(),
      userName: cache.GetLocalStorageByString("userName") || "",
      avatar: cache.GetLocalStorageByString("avatar") || "",
      menus: cache.GetLocalStorageByObject<any[]>("menus") || [],
      refreshToken: cache.GetLocalStorageByString("refreshToken") || undefined,
      isRefreshToken: false,
    },
  );

  const SET_TOKEN = (token: string) => {
    state.token = token;
    SetToken(token);
  }

  const SET_REFRESH_TOKEN = (token: string) => {
    state.refreshToken = token;
    cache.SetLocalStorageByString("refreshToken", token);
  }

  const REMOVE_TOKEN = () => {
    state.token = undefined;
    RemoveToken();
  }

  const REMOVE_REFRESH_TOKEN = () => {
    state.refreshToken = undefined;
    cache.RemoveLocalStorage("refreshToken");
  }

  const SET_USER_INFO = (user: { nick_name: string; avatar: string }) => {
    state.userName = user.nick_name;
    state.avatar = user.avatar;
    cache.SetLocalStorageByString("userName", user.nick_name);
    cache.SetLocalStorageByString("avatar", user.avatar);
  }

  const SET_IS_REFRESH_TOKEN = (isRefresh: boolean) => {
    state.isRefreshToken = isRefresh;
  }

  const REMOVE_USER_INFO = () => {
    state.userName = "";
    state.avatar = "";
    cache.RemoveLocalStorage("userName");
    cache.RemoveLocalStorage("avatar");
  }

  const SET_MENUS = (menus: any[]) => {
    // 移除动态路由
    state.menus.forEach((f) => {
      if (!router.hasRoute(f.name as string)) {
        return;
      }
      router.removeRoute(f.name as string);
    });

    state.menus = menus;
    cache.SetLocalStorageByObject("menus", menus);
  }

  const REMOVE_MENUS = () => {
    // 移除动态路由
    state.menus.forEach((f) => {
      if (!router.hasRoute(f.name as string)) {
        return;
      }
      router.removeRoute(f.name as string);
    });

    state.menus = [];
    cache.RemoveLocalStorage("menus");
  };

  /**
   * 登录
   * @param dt
   */
  const login = async (dt: { account: string; password: string }): Promise<{ code: number, data: any, msg:any }> => {
    const {
      data,
      status,
    } = await Login(dt)
    .catch((dt) => dt);

    try {
      if (status !== 200) {
        throw new Error("连接失败");
      }

      SET_TOKEN(data.data);

      // 刷新Token
      const refreshRes = await RefreshToken();
      SET_TOKEN(refreshRes.data.data.token);
      SET_REFRESH_TOKEN(refreshRes.data.data.refresh_token);

      // 此处可调用自己的方法获取用户数据，或者通过login接口直接返回数据

      const res = await GetUserPermission();
      SET_USER_INFO(res.data.data.user_info);
      viewTagStore.closeAllTag();
      SET_MENUS(res.data.data.menus);
    } catch (error) {
      REMOVE_TOKEN();
      return Promise.resolve({
        code: -1,
        data: null,
        msg: error,
      });
    }
    return Promise.resolve({ data } as any);
  }

  /**
   * 退出登录
   */
  const loginOut = () => {
    REMOVE_MENUS();
    REMOVE_USER_INFO();
    REMOVE_REFRESH_TOKEN();
    REMOVE_TOKEN();
    router.replace(import.meta.env.VITE_DEFAULT_START_ROUTER_PATH);
    // window.location.reload();
    // 重置路由缓存状态
    appStore.resetRouteState();
  }

  /**
   * 刷新Token
   */
  const refreshToken = async () => {
    try {
      if (!state.refreshToken) {
        throw new Error("会话失效");
      }

      SET_IS_REFRESH_TOKEN(true);
      SET_TOKEN(state.refreshToken);
      const { data } = await RefreshToken();
      SET_TOKEN(data.data.token);
      SET_REFRESH_TOKEN(data.data.refresh_token);
      SET_IS_REFRESH_TOKEN(false);
    } catch (err) {
      throw new Error("会话失效");
    }
  };

  const resetRefreshToken = () => {
    SET_IS_REFRESH_TOKEN(false);
  };

  return {
    ...toRefs(state),
    login,
    loginOut,
    refreshToken,
    resetRefreshToken,
  }
})